import machine, os
import utime
import micropython
import json
micropython.alloc_emergency_exception_buf(100)

class IRReceiver(object):
    #用来接收指令
    def __init__(self, gpioNum):
        self.enabled = False
        #设置中断
        self.irPin = machine.Pin(gpioNum, machine.Pin.IN, machine.Pin.PULL_UP)
        self.irPin.irq(trigger=machine.Pin.IRQ_RISING | machine.Pin.IRQ_FALLING, handler=self.__irq_handler)

        self.val_list = [0 for x in range(1000)] #临时的缓冲区，最多1000个脉冲，多了就溢出了
        self.index = 0
        self.begin = 0
        self.values = None #学习后的值
        self.timeout = 10000
    def __irq_handler(self, source):
        #中断程序，用来捕获脉冲时间
        if not self.enabled or self.index>=1000: #避免缓冲区溢出
            return
        thisComeInTime = utime.ticks_us()
        if self.begin == 0:
            self.begin = thisComeInTime
            self.index = 0
            return

        self.val_list[self.index] = utime.ticks_diff(thisComeInTime, self.begin)
        self.begin = thisComeInTime
        self.index += 1

    def stop(self):
        self.enable = False

    def start(self):
        self.enabled = True #运行标志
        try:
            time_start = utime.ticks_ms()
            while self.enabled and (utime.ticks_diff(utime.ticks_ms(), time_start) < self.timeout): #在超时时间范围内，持续循环
                
                utime.sleep_ms(200)
                if utime.ticks_diff(utime.ticks_us(), self.begin) > 800000 and self.index > 0:
                    #从缓冲区读取数据
                    self.values = []
                    n = 0
                    for i in self.val_list:
                        if (self.val_list[n] == 0) and\
                           (self.val_list[n + 1] == 0) and\
                           (self.val_list[n + 2] == 0) and\
                           (self.val_list[n + 3] == 0) and\
                           (self.val_list[n + 4] == 0) and\
                           (self.val_list[n + 5] == 0):
                            break #连续6个空位，后面的数据无效，舍弃
                        else:
                            self.values.append(i)
                            n += 1
                    #对缓冲区重新初始化，为下次接收做准备
                    self.val_list = [0 for x in range(1000)]
                    self.index = 0
                    self.begin = 0
                    break
        finally:
            self.stop()

#用来发送指令
class IRSender(object):
    def __init__(self, gpioNum):
        self.irLed = machine.Pin(gpioNum, machine.Pin.OUT)
        self.pwmObj = machine.PWM(self.irLed, freq=38000, duty=0) #38KHz的方波脉冲
    
    def send(self, values: [int]):
        self.pwmObj.deinit()
        self.pwmObj.init()
        self.pwmObj.freq(38000)
        self.pwmObj.duty(0)
        utime.sleep_ms(100)
        ctrlListLen = len(values)
        for i in range(ctrlListLen):
            if i % 2 == 0:
                self.pwmObj.duty(341) #占空比为大约1/3的方波，偶数位高电平
            else:
                self.pwmObj.duty(0) #奇数位低电平
            utime.sleep_us(values[i]) #间隔的微秒数

        self.pwmObj.duty(0)
        utime.sleep_ms(100)


class IRCmds(object):
    #用来保存命令，命令是一个整数数组，记录了高低电平持续的时间
    def __init__(self, file_name):
        self.file_name = file_name
        self.data = None
    
    def load(self):
        if self.data:
            #加载过就不再重复加载了
            return
        if self.file_name in os.listdir(): #判断文件是否存在
            with open(self.file_name, 'r') as f:
                self.data = json.load(f)
        if self.data == None: #如果没有数据就初始化个空的
            self.data = {}
            
    def save(self):
        #保存数据
        if self.data==None:
            self.data = {}
        with open(self.file_name, 'w') as f:
            json.dump(self.data, f)

    def get_cmd(self, key: str):
        self.load()
        return self.data.get(key)
    
    def set_cmd(self, key: str, values:[int]):
        self.load()
        self.data[key]=values
        self.save()

    def get_keys(self):
        self.load()
        return list(self.data.keys())

if __name__ == '__main__':
    r = IRReceiver(14)
    r.start()

    if r.values and len(r.values)>5:
        while True:
            print("send")
            sender = IRSender(12)
            sender.send(r.values)
            utime.sleep_ms(1000)
